#include<iostream>
#include<vector>
#include<queue>
using namespace std;

using ll=long long;
const ll MAX=1e18;//因为题目1≤ w ≤10的9次方就是最大的了
ll map[2008][2008];//2 ≤ n、m ≤ 2×103
bool mark[2008][2008];//标记是否访问
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};//四个方向移动

ll ans=MAX;//记录最后的结果，设置初始为最大MAX
//定义一下图中每个节点的结构体，记录各个信息
struct Node{
	int x;
	int y;
	ll weight;
	Node(int X,int Y,ll w):x(X),y(Y),weight(w){}
	Node(){}
};

queue<Node>q;//BFS队列

ll BFS(int start_x,int start_y,int end_x,int end_y,ll w){
	//确定搜索最大边界，避免浪费时间
	int n = max(start_x, end_x);
	int m = max(start_y, end_y);
//初始化标记数组 mark，所有点设为未访问。	
	for (int i = 1; i <= n; i++){
		for (int j = 1; j <= m; j++)
			mark[i][j] = 0;
}
   //将起点加入队列，并标记为已访问
   q.push(Node(start_x,start_y,0));
   mark[start_x][start_y]=1;
   
   ll Min=MAX;//记录值
   while(!q.empty()){
   	Node cur=q.front() ;
   	q.pop();
   	//如果当前节点是终点，则更新全局答案 ans
   	if (cur.x == end_x && cur.y == end_y)
		{
			ans = min(ans, cur.weight);
		}
   //有权值这里就加了
   /*从任何包含时空通道的单元出发，阿迪可以去往任何包含时空通道的其他单元，
   从时空通道( i, j )到时空通道( x, y ) 的时间成本总和为 aij + axy。*/
   	if (map[cur.x][cur.y] > 0)
		{
			Min = min(cur.weight + map[cur.x][cur.y], Min);
		}
	//这里是加上每次移动花的时间
	for (int i = 0; i < 4; i++)
		{//遍历四个方向
			int x = cur.x + dir[i][0];
			int y = cur.y + dir[i][1];
			//值为-1的地方，在这样的判断下不会进入队列
			if (x <= n && x >= 1 && y <= m && y >= 1 && map[x][y] != -1 && mark[x][y] != 1)
			{
				q.push(Node(x, y, cur.weight + w));//把四个方向都压进去了
				mark[x][y] = 1;
			}
		}
   
}
        return Min;
}

int main(){
	ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //因为输入太慢了，要关掉输出流
	int n,m,w;
	cin>>n>>m>>w;
for (int i = 1; i <= n; i++){
	for (int j = 1; j <= m; j++)
	
		cin>>map[i][j];
	}	
	//边界为障碍物（不可 = x走）。
	for (int i = 0; i <= n; i++)
	{
		map[i][0] = -1;
	}

	for (int j = 0; j <= m; j++)
	{
		map[0][j] = -1;
	}
	ans = min(ans, BFS(1, 1, n, m, w) + BFS(n, m, 1, 1, w));
    //如果找到有效路径，输出结果；否则输出 -1。
	if (ans != MAX)
	{
		cout << ans << '\n';
	}
	else
	{
		cout << -1 << '\n';
	}
	return 0;
}